/*
 * Title:        CloudScheduler Toolkit
 * Description:  a Toolkit for Modeling and Simulation of Job Scheduling and Resource Provisioning in Cloud System
 * Licence:      GPL - http://www.gnu.org/copyleft/gpl.html
 * Author:       Fuhui Wu
 *
 * Copyright (c) 2013-2014, The National University of Defense Technology, China
 */

package org.nudt.jCloud.simulation;

import org.nudt.jCloud.util.Log;

public abstract class SimEntity implements Cloneable{
	private String name;
	private int id;
	private SimEvent eventBuf;
	private int state;
	
	public static final int RUNNABLE = 0;
	public static final int WAITING = 1;
	public static final int HOLDING = 2;
	public static final int FINISHED = 3;
	
	public SimEntity(String name) {
		setName(name);
		setId(-1);
		setState(RUNNABLE);
	}
	
	public abstract void startEntity();
	
	public abstract void processEvent(SimEvent event);
		
	public void send(int dest, double delay, int tag, Object data){
		CloudSchedSIM.send(id, dest, delay, tag, data);
	}
	public void sendNow(int dest, int tag, Object data){
		send(dest, 0, tag, data);
	}
	
	protected void processOtherEvent(SimEvent ev) {
		if (ev == null) {
			Log.println("CloudInformationService.processOtherEvent(): "
					+ "Unable to handle a request since the event is null.");
			return;
		}

		Log.println("CloudInformationSevice.processOtherEvent(): " + "Unable to handle a request from "
				+ CloudSchedSIM.getEntityName(ev.getSrc()) + " with event tag = " + ev.getTag());
	}

	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @return the id
	 */
	public int getId() {
		return id;
	}

	/**
	 * @param id the id to set
	 */
	public void setId(int id) {
		this.id = id;
	}

	/**
	 * @return the eventBuf
	 */
	public SimEvent getEventBuf() {
		return eventBuf;
	}

	/**
	 * @param eventBuf the eventBuf to set
	 */
	public void setEventBuf(SimEvent eventBuf) {
		this.eventBuf = eventBuf;
	}

	public void run() {
		SimEvent ev = eventBuf != null ? eventBuf : getNextEvent();
		
		while(ev != null){
			processEvent(ev);
			ev = getNextEvent();
		}
		
		eventBuf = null;
		
	}

	private SimEvent getNextEvent() {
		return getNextEvent(CloudSchedSIM.SIM_ANY);
	}

	private SimEvent getNextEvent(Predicate p) {
		if(!CloudSchedSIM.isRunning()){
			return null;
		}
		if(numEventsWaiting(p)>0){
			return selectEvent(p);
		}
		return null;
	}

	private SimEvent selectEvent(Predicate p) {
		if(!CloudSchedSIM.isRunning()){
			return null;
		}
		return CloudSchedSIM.select(id, p);
	}

	private int numEventsWaiting(Predicate p) {
		return CloudSchedSIM.waiting(id, p);
	}

	/**
	 * @return the state
	 */
	public int getState() {
		return state;
	}

	/**
	 * @param state the state to set
	 */
	public void setState(int state) {
		this.state = state;
	}

}
